package zeno.project.springboot.controller.core;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import zeno.project.springboot.constant.SystemConstant;
import zeno.project.springboot.dao.SysUserMapper;
import zeno.project.springboot.entity.system.SysUser;
import zeno.project.springboot.util.MappingTool;

import javax.servlet.http.HttpServletRequest;

/**
 * @author ZhiYong
 * @ClassName UserController.java
 * @Description 使用 Shiro 进行认证
 * @createTime 2021/04/17 22:16:00
 * 接口一： 使用 http://localhost:9494/user/admin 来验证身份认证
 * 接口二： 使用 http://localhost:9494/user/student 来验证角色认证
 * 接口三： 使用 http://localhost:9494/user/teacher 来验证权限认证
 * 接口四： 使用 http://localhost:9494/user/login 来实现用户登录
 * 流程一： 直接访问接口一（此时还未登录），认证失败，跳转到 login.html 页面让用户登录，登录会请求接口四，实现用户登录功能，此时 Shiro 已经保存了用户信息了。
 * 流程二： 再次访问接口一（此时用户已经登录），认证成功，跳转到 success.html 页面，展示用户信息。
 * 流程三： 访问接口二，测试角色认证是否成功。
 * 流程四： 访问接口三，测试权限认证是否成功。
 */
@Controller
@RequestMapping("/user")
@Api(value = "使用 Shiro 进行认证")
public class UserController {
    @Autowired
    private SysUserMapper sysUserMapper;

    /**
     * 用户登录接口
     * @param sysUser user
     * @param request request
     * @return string
     */
    @PostMapping("/login")
    @ApiOperation(value = "登陆")
    public String login(SysUser sysUser, HttpServletRequest request, Model model) {
        SysUser user = new SysUser();
        MappingTool.mapper(sysUser, user);
        // 根据用户名和密码创建token
        UsernamePasswordToken token = new UsernamePasswordToken(user.getAccount(), user.getPassword());
        // 获取subject认证主体
        Subject subject = SecurityUtils.getSubject();
        try{
            // 开始认证，这一步会跳到我们自定义的realm中
            subject.login(token);
            request.getSession().setAttribute(SystemConstant.USER_SESSION, user);
            user = sysUserMapper.getByAccount(user.getAccount());
            model.addAttribute("result", "登陆成功!");
            model.addAttribute(SystemConstant.USER_SESSION, user);
            return "success";
        }catch(Exception e){
            e.printStackTrace();
            request.getSession().setAttribute(SystemConstant.USER_SESSION, user);
            request.setAttribute("error", "登录名或密码错误！");
            model.addAttribute("error", "登录名或密码错误!");
            return "login";
        }
    }

    /**
     * 身份认证测试接口
     * @param request request
     * @return success
     */
    @RequestMapping("/admin")
    @ApiOperation(value = "身份认证测试接口")
    public String admin(HttpServletRequest request, Model model) {
        Object user = request.getSession().getAttribute(SystemConstant.USER_SESSION);
        model.addAttribute(SystemConstant.USER_SESSION, user);
        return "success";
    }

    /**
     * 角色认证测试接口
     * @param request request
     * @return success
     */
    @RequestMapping("/student")
    @ApiOperation(value = "角色认证测试接口")
    public String student(HttpServletRequest request, Model model) {
        model.addAttribute("result", "角色认证测试接口");
        return "success";
    }

    /**
     * 权限认证测试接口
     * @param request request
     * @return success
     */
    @RequestMapping("/teacher")
    @ApiOperation(value = "权限认证测试接口")
    public String teacher(HttpServletRequest request, Model model) {
        model.addAttribute("result", "权限认证测试接口");
        return "success";
    }
}
